#!/usr/bin/python

 # Copyright (c) 2011 Robert Kirchgessner <rkirchge@gmail.com>
 #                    Carlo Pascoe <carlo.pascoe@gmail.com>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
 # in the Software without restriction, including without limitation the rights
 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 # copies of the Software, and to permit persons to whom the Software is
 # furnished to do so, subject to the following conditions:
 #  
 # The above copyright notice and this permission notice shall be included in
 # all copies or substantial portions of the Software.
 # 
 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.

# @brief Converts a Mif 2.5 file into a dotty script
# @author Robert Kirchgessner <kirchgessner@chrec.org>
# @date 2011-03-26

from xml.sax import *
import argparse
import sys
import networkx as nx


class Mif25Handler(ContentHandler):
  def __init__(self, data):
    ContentHandler.__init__(self)
    self.data = data
    self.interactorName = ""
    self.interaction = False 
    self.interactionList = list()
    self.iref = False

  def startElement(self, name, attrs):
    if name == "interaction":
      self.interactionList = list()
      self.interaction = True

    if name == "interactor":
      self.interactorId = attrs["id"]
      #If we define an interaction in the interaction add the id
      if(self.interaction == True):
        self.interactionList.append(attrs["id"])  

    if name == "secondaryRef":
      # Use the yeast database name for the proteins
      if(attrs["db"] == "cygd"):
        self.interactorName = attrs["id"]

    if name == "interactorRef":
      self.iref = True
  
  def endElement(self, name):
    if name == "interactor":
      if(self.interactorName == ""):
        print "ERROR! XML FILE DID NOT SPECIFY INTERACTOR Y-id"
	exit -1
      
      self.data.add_interactor(self.interactorId, self.interactorName)
      self.interactorName = ""

    if name == "interaction":
      self.data.add_interaction(self.interactionList)
      self.interaction = False

    if name == "interactorRef":
      self.interactionList.append(self.str0)
      self.iref = False
  

  def characters(self, chrs):
    self.str0 =  chrs


class MifData():
  def __init__(self):
    self.interactionList = list()
    self.interactorList = dict()

  def add_interactor(self, id, name):
    self.interactorList[id] = name

  def add_interaction(self, interactors):
    for x in range(len(interactors)):
      current = interactors[x]
      for y in interactors[x+1:]:
        self.interactionList.append(list([current, y]))

  def nVertice(self):
    return len(self.interactorList)

  def nEdge(self):
    return len(self.interactionList) 

  def write_edgelist(self, filename):
    f = open(filename, 'w')
    f.write(str(self.nVertice()) + "\n")
    for x in self.interactionList:
      f.write(x[0] + " " + x[1] + "\n")
    f.close()

#Main function
def main(fname_in, fname_out, out_type):
  print "Input File: " + fname_in
  print "Output File: " + fname_out

  data = MifData()

  print "Parsing..."

  try:
    parse(fname_in, Mif25Handler(data))  
  except:
    print "Error"
    raise

  print "Parsing complete."
  print "Found " + str(data.nVertice()) + " vertices and " + str(data.nEdge()) + " edges"
  print "Building output.."

  if out_type == "edge":
    data.write_edgelist(fname_out)

#  if out_type == "dot":
#    data.write_graph(fname_out)

  print "Output complete."


if __name__ == "__main__":
  parser = argparse.ArgumentParser()
  parser.add_argument( 'infile', action='store')
  parser.add_argument( 'outfile', action='store' )
  parser.add_argument( '--out_type', default='edge', choices=['edge', 'dot'])
  args = parser.parse_args(sys.argv[1:])
  main(args.infile, args.outfile, args.out_type)

